package com.authsphere.security.configurer.social.filter;

import com.authsphere.security.account.api.bind.AccountNotBindContext;
import com.authsphere.security.account.api.bind.exception.AccountBindException;
import com.authsphere.security.account.api.bind.user.ExternalUser;
import com.authsphere.security.common.AbstractRequestBodyAuthenticationFilter;
import com.authsphere.security.configurer.social.ThirdAuthorizationAuthenticationToken;
import com.authsphere.security.configurer.social.entity.ThirdAuthorizationEntity;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.model.AuthUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;

/**
 * @program: AuthSphere
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/18 20:35
 **/
public class ThirdAuthorizationRequestBodyAuthenticationFilter extends AbstractRequestBodyAuthenticationFilter<ThirdAuthorizationEntity> {
    private final static String DEFAULT_PROCESS_URL = "/third/login";
    private final static String DEFAULT_BIND_URL = "/sns/bind";
    private final static String DEFAULT_MODULE_TYPE = "third";

    private final static String DEFAULT_APP_CLIENT_HEADER = "User-Agent";
    private final static String DEFAULT_APP_CLIENT_VALUE = "AppClient";

    private String appClientHeader = DEFAULT_APP_CLIENT_HEADER;
    private String appClientValue = DEFAULT_APP_CLIENT_VALUE;
    private String bindUrl = DEFAULT_BIND_URL;

    private final AuthStateCache authStateCache;


    public ThirdAuthorizationRequestBodyAuthenticationFilter(AuthStateCache authStateCache) {
        super(DEFAULT_MODULE_TYPE, DEFAULT_PROCESS_URL, ThirdAuthorizationEntity.class);
        Assert.notNull(authStateCache, "authStateCache cannot be null");
        this.authStateCache = authStateCache;
    }

    public ThirdAuthorizationRequestBodyAuthenticationFilter(String moduleType, AuthStateCache authStateCache) {
        super(moduleType, DEFAULT_PROCESS_URL, ThirdAuthorizationEntity.class);
        Assert.notNull(authStateCache, "authStateCache cannot be null");
        this.authStateCache = authStateCache;
    }


    @Override
    protected Authentication buildAuthenticationToken(HttpServletRequest request, HttpServletResponse response, ThirdAuthorizationEntity requestJsonBody) {
        String state = requestJsonBody.getState();
        if (StringUtils.isBlank(state)) {
//            throw new CsrfStateException("当前认证环境存在异常，请重新授权");
        }
        String cachedState = authStateCache.get(state);
        if (!StringUtils.equals(cachedState, state)) {
//            throw new CsrfStateException("当前认证环境state不一致，请重新授权");
        }
        return new ThirdAuthorizationAuthenticationToken(requestJsonBody);
    }

//    @Override
//    protected Authentication afterAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
//        checkAccountLockout(authentication, true);
//        if (authentication instanceof ThirdAuthorizationAuthenticationToken authenticationToken) {
//            if (!authenticationToken.hasBind()) {
//                AccountNotBindContext context = buildContext(authenticationToken);
//                context.setAppClient(isAppRequest(request));
//                try {
//                    this.getAccountBindService().noBind(request, response, context);
//                    return null;
//                } catch (Exception e) {
//                    throw new AccountBindException("账号绑定异常", e);
//                }
//            }
//        }
//        return authentication;
//    }

    private AccountNotBindContext buildContext(ThirdAuthorizationAuthenticationToken authenticationToken) {
        AuthUser authUser = (AuthUser) authenticationToken.getPrincipal();
        return new AccountNotBindContext(buildExternalUser(authUser), this.bindUrl);
    }

    private ExternalUser buildExternalUser(AuthUser authUser) {
        ExternalUser externalUser = new ExternalUser();
        externalUser.setUuid(authUser.getUuid());
        externalUser.setUsername(authUser.getUsername());
        externalUser.setNickname(authUser.getNickname());
        externalUser.setAvatar(authUser.getAvatar());
        externalUser.setBlog(authUser.getBlog());
        externalUser.setCompany(authUser.getCompany());
        externalUser.setLocation(authUser.getLocation());
        externalUser.setEmail(authUser.getEmail());
        externalUser.setRemark(authUser.getRemark());
        externalUser.setGender(Integer.parseInt(authUser.getGender().getCode()));
        externalUser.setSource(authUser.getSource());
        externalUser.setRawUserInfo(authUser.getRawUserInfo().toString());
        externalUser.setSnapshotUser(false);
        return externalUser;
    }

    private boolean isAppRequest(HttpServletRequest request) {
        String userAgent = request.getHeader(this.appClientHeader);
        return userAgent != null && userAgent.contains(this.appClientValue); // 自定义判断逻辑
    }

    public void setAppClientHeader(String appClientHeader) {
        this.appClientHeader = appClientHeader;
    }

    public void setAppClientValue(String appClientValue) {
        this.appClientValue = appClientValue;
    }

    public void setBindUrl(String bindUrl) {
        this.bindUrl = bindUrl;
    }
}
